如何评价一个开源项目?是它了
本文由X-lab开放实验室博士生赵生宇创作
从 2015 年开始参与到开源社区,到 2018 年进入阿里开始做开源运营相关的工作,直到今天在 X-lab 已经读博两年,事实上一直在探索如何更准确地评价一个开源项目是否健康。所以整体回顾一下一直以来的一些工作,并对每一步的思考有一些总结。也希望可以有更多对社区度量感兴趣的朋友参与到讨论之中,本人的联系方式见关于页(http://blog.frankzhao.cn/about)
从 2015 年 Apache Roadshow 开始参与到开源社区,更多的是参与开源社每年的活动。直到 2018 年进入阿里之前,其实我并没有真正深入参与到某个开源技术社区中,也没有真正接触过开源运营,对开源的理解还是一群牛人聚在一起好玩而已。直到 2018 年进入阿里,我对开源项目的评判认知依然非常模糊,GitHub star 就是最直观的一个指标,另外如果来自基金会或大厂,一般不会太差,还有如果技术大佬都说好,自然是好的项目。这可能依然是大部分开源运营的基本逻辑,因为从大众视角看,最简单直接的才是最吸引眼球的。
后来,小狼给我提出的问题是到底是否能知道开源世界有多少项目,在哪些领域,以及如何判断这些项目的好坏,此时还在 2018 年,对于绝大部分公司来讲,开源社区的量化可能都还没有开始起步。
随着对 GitHub 数据的深入调研,发现了基于历史行为日志数据的分析方法,这种方法下不需要再使用 API 去单独获取每一个仓库的信息,就可以在全域范围内统计 GitHub 所有仓库和开发者的行为,这对于上千个项目的指标统一计算是极大的利好。于是最早对 GitHub 全域日志的探索分享出现在了 Open Source Summit 2019 上,当时基于 Google BigQuery 中的收费数据服务对 2018 全年的 GitHub 全域日志做了一些简单的分析工作。
也是在这次的分享上,提出了基于GitHub 行为数据的加权活跃度算法,具体的计算方式为: 其中的 为开发者活跃度,而 为上述五种行为事件由该开发者触发的发生次数, 为该行为事件的加权比例。按照一个简单的价值评判,我们可以将这个值设置为 1 - 5,即 Issue 评论每个计 1 分、发起 Issue 每个计 2 分、发起 PR 每个计 3 分、PR 上的代码 review 评论每个计 4 分、PR 合入一个计 5 分。在计算出每个开发者的活跃度后,可以通过一种加权和的方式来计算项目的活跃度,之前给出的方式是: 即项目的活跃度为所有开发者活跃度的开方和,这里开方是为了降低核心开发者过高的活跃度带来的影响。
从开源办公室的角度而言,我们必须有一个“北极星”指标。对于一些开源创业公司或具体的开源项目团队而言,可以通过监控或观察多个指标来判断项目的健康与否。但对于有 2000 多个开源项目的企业而言,要同时监控这么多项目的健康度,就需要一个聚合的指标,否则人力成本过高。
由于 star、fork 等行为属于开发者的单向行为,虽然表示了对项目的一种关注,但并不对项目产生具体贡献,所以没有纳入到活跃度的计算之中,即刷 star 等行为在活跃度算法下无效。
即便当时默认的贡献者(contributor)的定义为代码贡献者,但从实际角度出发,参与到社区中的所有开发者,包括提交 bug、参与讨论、参与代码 review 的开发者事实上都对项目是有贡献的,所以在计算中并不是仅计入代码贡献,而是将讨论等也纳入。
对于五种事件对应的权重应该是多少,其实在这里是相当主观的,1 - 5 是一个非常简单粗暴的赋值方式,但事实上这个权重集是在阿里最重要的一些战略级开源项目的负责人共识下产生的,并且对 PR 的 review 给出了非常高的 4 分,也是鼓励大家多进行基于 GitHub 的异步 review。
从开发者活跃度到项目活跃度的计算,我们对每个开发者的活跃度进行了开方,这里所给出的价值观是:那些核心开发者非常活跃,但总体参与人数较少的社区,其活跃度不应高于核心开发者虽然不太活跃,但参与贡献人数更多的社区。本质上是对个体开发者活跃度进行了一个削减。
总体而言,这个活跃度的计算方式是一种简单的基于 GitHub 行为数据的加权统计算法,权值属于专家经验赋值,带有一定的价值导向。并且从开发者活跃度到项目活跃度的计算也具有一定的价值导向,即间接的将贡献者数量作为一个重要因素引入到项目活跃度中。
事实上这个活跃度计算方式直到现在,也是每年的 GitHub 洞察报告中非常重要的一部分,并且也进行过一些迭代。例如在 2020 年的报告中,对于 merge PR 的权重,我们从 5 分降到了 2 分,原因是事实上 open PR 已经有了一次 3 分的计入,merge 额外给 5 分的权重偏高。另外也通过 PR 的代码行数对权重进行了修正,即对于单 PR 代码行数始终的给出较高的权重,而修改非常少或非常多的 PR 都做了相应的削减,本身也算是一种价值导向。同时我们在 2020 年的报告中也引入了 star 和 fork 的数量,即使只作为一种关注度指标,事实上对于理解项目的活跃度也有一定帮助,分别给出了 1 和 2 的权重,其实也是非常低的。
但活跃度的计算也存在一些显而易见的问题,例如:
到底哪些数值需要被纳入,例如 star、fork 是否应该被纳入,是不太确定的。尤其是在活跃度这样一个概念下,那些对项目没有带来实际反馈的行为是否要纳入进来极为微妙。
不同行为的权重是人为指定的,虽然包含了一定的专家经验,但这些数值的大小其实是还是具有相当的主观性,尤其是在项目之间比较时,权重的微小差别就会带来一些总体活跃度的波动。
这种活跃度计算方式缺乏基线。由于这里的活跃度是对一段时间内的行为次数的统计,所以时间段不同,则活跃度不同,时间段越长,活跃度越高。因此在不同时间段上无法进行直观的比较,这种缺乏基线的计算方式对于给出活跃度的参考阈值是不友好的。
这种活跃度计算方式在仓库层面不具有线性可加性。为了引入贡献者数量的因素,在仓库活跃度求和时对开发者活跃度开方,这个非线性操作导致了仓库活跃度在时间区间不能线性可加,这对多时间段的运算造成了比较大的影响,使得一些中间结果无法被复用。
个人活跃度到仓库活跃度的开方操作本身也是一个人为的经验做法,本质上就是想引入一个一阶导数单调递增,二阶导单调递减的函数来进行修正,模拟一种边际效益递减效应。显然不仅是开方,对数函数也满足这种性质,而且对数函数在此类计算中非常常用,而我当时选用开方是考虑了计算效率问题,因为开方运算在很多语言下都比对数运算要更快。
只要是简单的统计指标来进行计算,就一定无法避免刷指标的行为。事实上,当我们在阿里内部开始推行这个指标体系时,有部分开发者的活跃度有了一个跳变。原因其实是原先这个项目的负责人不知道如何在 GitHub 进行 review,在看到这个指标体系之前都是在即时通讯工具中进行同步聊天的 review,但在我们的推广和教育后,对过去的一些代码 review 进行了集中的补充。这也是我们认为好的指标体系可以起到的作用,即便是刷指标,但我们认为该指标是起到了正向的引导作用。而且之后也没有发现有其他项目通过刻意增加回复数量、拆分 PR 等方式恶意刷活跃度的情况,毕竟开方操作本身使得个别账号的这种刷分行为对整体仓库的影响是有限的。因此在这个指标下的刷分行为目前来看是起到了预期的价值导向作用。
除每年的数字洞察报告外,我们并没有刻意去推广这个指标。但我们持续在为阿里提供这样的服务,以便他们可以更好的观察自己项目的状态。例如阿里内部的开源项目大屏中,我们将 star 和 fork 从活跃度中拆分出来,独立成为一个关注度指标,即对项目有贡献的行为进入活跃度,而对项目有关注,但没有实际回馈的行为进入关注度。通过这种方式将两种不同的增长模式给区分出来。我们也开始尝试利用活跃度分布来判断社区的健壮性,有点类似于公交系数,如果头部贡献者的活跃比例较低,而大部分活跃都来自长尾贡献者,则社区更加健壮。并且我们也开始提供和尝试基于协作网络的一些洞察能力。
而金融开源社区也有很多项目开始采用类似这种指标体系,而浦发银行也曾发文,在以上行为数据外加入了时间序列上的一些衰减指数等。
虽然活跃度依然存在许多问题,尤其是在持续的大规模运算和可扩展性上的问题。但由于其直观、易理解,可解释性强,事实上依然是我们实验室目前广泛使用的一种计算方式。并且也已经在很多项目中有落地,但我个人还是希望可以有更好的指标体系和算法框架,来更好的利用开源生态和网络来对项目做出更加有效的衡量。
往期精彩回顾